package ve.com.wayoyo.wuml_case.DibujoDiagramas;

import java.io.FileOutputStream;
import java.io.IOException;

import ve.com.wayoyo.wuml_case.NuevoDiagrama;
import ve.com.wayoyo.wuml_case.R;
import ve.com.wayoyo.wuml_case.UserPref;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Environment;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Toast;

public class VistaDiagrama extends View {

	public final static int IDLE = 0;
	public final static int SCROLLING = 1;
	public final static int SCALING = 2;
	public final static int CREATING_ITEM = 3;
	public final static int MOVING_ITEM = 4;
	public final static int ITEM_SELECTED = 5;
	public final static int CONNECTING_ITEMS = 6;
	public final static int CONNECTOR_SELECTED = 7;
	public final static int RESET = 99;


	private static float MIN_ZOOM = 0.5f;
	private static float MAX_ZOOM = 3.0f;
	private static VistaDiagrama _instance;

	private int _xOffset = 0;
	private int _yOffset = 0;
	private float _Scale = 1.0f;


	private int _xTouch = 0;
	private int _yTouch = 0;

	private int _currentState = IDLE;

	private Diagrama _diagrama;
	private Paint _backgroundPaint;
	private Paint _imagePaint;

	private ScaleGestureDetector detector;
	//	private String titulo = null;
	private boolean showHelpNewElement;
	private boolean _moveFlag;

	private String _tipoComponente;


	//Bitmaps de los cuadros de ayuda
	Bitmap HelpNewElementBitmap = BitmapFactory.decodeResource(this.getContext().getResources(),R.drawable.cuadroayuda1);


	public VistaDiagrama(Context context,Diagrama diagrama){
		super(context);
		_backgroundPaint = new Paint();
		_backgroundPaint.setColor(UserPref.getInstancia().getColorFondoDiagramas());
		this._diagrama = diagrama;
		_imagePaint = new Paint();
		detector = new ScaleGestureDetector(getContext(), new ScaleListener());
		_instance = this;
	}

	public Diagrama getDiagrama(){
		return _diagrama;
	}

	public void set_diagrama(Diagrama _diagrama) {
		this._diagrama = _diagrama;
		invalidate();
	}

	@Override
	protected void onDraw(Canvas c){
		super.onDraw(c);
		c.drawPaint(_backgroundPaint);
		_diagrama.Dibujar(c,_xOffset , _yOffset, _Scale);
		if(showHelpNewElement == true){
			c.drawBitmap(HelpNewElementBitmap, (c.getWidth()/2)-200, (c.getHeight()/2)-200, _imagePaint);
		}
	}

	@Override
	public boolean onTouchEvent (MotionEvent event) {
		detector.onTouchEvent(event);
		NuevoDiagrama diag = (NuevoDiagrama) this.getContext();	  
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			// store the current touch coordinates for scroll calculation
			_xTouch = (int) event.getX();
			_yTouch = (int) event.getY();
			if(_currentState != CONNECTING_ITEMS && _currentState != CONNECTOR_SELECTED){
				_diagrama.resetFocus();
			}   
			if(_currentState == CREATING_ITEM)
			{			
				Componente comp = FactoryComponente.getComponente(_tipoComponente);	
				Point anchor = new Point();

				anchor.set((int)((_xTouch)/(_Scale)-_xOffset), (int)((_yTouch)/(_Scale)-_yOffset));
				comp.setAnchor(anchor);
				TituloComponente myDialog = new TituloComponente(this.getContext(),"Indique el nombre","Titulo",comp);
				myDialog.show();
				_currentState = RESET;
				showHelpNewElement = false;
				invalidate();
			}else if (_currentState == CONNECTING_ITEMS){
				Point touchPoint = new Point();
				touchPoint.set((int)((_xTouch)/(_Scale)-_xOffset), (int)((_yTouch)/(_Scale)-_yOffset));
				_currentState = _diagrama.checkOnTouch(touchPoint,"Connect");
				if(_currentState == IDLE){
					_currentState = CONNECTING_ITEMS;
				}
				invalidate();
			}else if(_currentState == CONNECTOR_SELECTED ){

			}else{
				Point touchPoint = new Point();
				touchPoint.set((int)((_xTouch)/(_Scale)-_xOffset), (int)((_yTouch)/(_Scale)-_yOffset));
				_currentState = _diagrama.checkOnTouch(touchPoint,"Select");
				if(_currentState == ITEM_SELECTED){
					if (_diagrama.getSelectedItem() instanceof CompClase) {					
						diag.cambioMenu(NuevoDiagrama.MENU_CLASE);
						_tipoComponente = "Clase";
					}
					if (_diagrama.getSelectedItem() instanceof CompInterface) {					
						diag.cambioMenu(NuevoDiagrama.MENU_INTERFACE);
						_tipoComponente = "Interface";
					}
					if (_diagrama.getSelectedItem() instanceof CompAbstract) {					
						diag.cambioMenu(NuevoDiagrama.MENU_ABSTRACT);
						_tipoComponente = "Abstract";
					}
				}else if(_currentState == CONNECTOR_SELECTED){
					diag.cambioMenu(NuevoDiagrama.MENU_CONECTOR);
					_moveFlag = true;
				}else{
					diag.cambioMenu(NuevoDiagrama.MENU_PRINCIPAL);	
				}
				invalidate();
			}
		}else if (event.getAction() == MotionEvent.ACTION_MOVE) {
			// touch starts moving, set the flag
			if(_currentState == IDLE){
				_currentState = SCROLLING;
			}else if(_currentState ==  ITEM_SELECTED){
				_currentState = MOVING_ITEM;
			}

			if( _currentState == SCROLLING || _currentState == CONNECTING_ITEMS || _currentState == CONNECTOR_SELECTED ){ 	
				// get the new offset
				if(Math.abs(_xTouch - (int) event.getX()) > 10 || Math.abs(_yTouch - (int) event.getY()) > 10){
					_moveFlag = true;
				}
				_xOffset -= _xTouch - (int) event.getX();
				_yOffset -= _yTouch - (int) event.getY();
				invalidate();
			}
			if(_currentState == MOVING_ITEM){
				_diagrama.moverItemSeleccionado((int)(-(_xTouch - (int) event.getX())/_Scale),(int)(-(_yTouch - (int) event.getY())/_Scale));
				invalidate();
			}

			// store the last position
			_xTouch = (int) event.getX();
			_yTouch = (int) event.getY();
		} else if (event.getAction() == MotionEvent.ACTION_UP) {
			if(_currentState == CONNECTOR_SELECTED && !_moveFlag ){
				_diagrama.resetFocus();
				Point touchPoint = new Point();
				touchPoint.set((int)((_xTouch)/(_Scale)-_xOffset), (int)((_yTouch)/(_Scale)-_yOffset));
				_currentState = _diagrama.checkOnTouch(touchPoint,"Select");
				if(_currentState == ITEM_SELECTED){
					if (_diagrama.getSelectedItem() instanceof CompClase) {					
						diag.cambioMenu(NuevoDiagrama.MENU_CLASE);
						_tipoComponente = "Clase";
					}
					if (_diagrama.getSelectedItem() instanceof CompInterface) {					
						diag.cambioMenu(NuevoDiagrama.MENU_INTERFACE);
						_tipoComponente = "Interface";
					}
					if (_diagrama.getSelectedItem() instanceof CompAbstract) {					
						diag.cambioMenu(NuevoDiagrama.MENU_ABSTRACT);
						_tipoComponente = "Abstract";
					}
				}else if(_currentState == CONNECTOR_SELECTED){
					diag.cambioMenu(NuevoDiagrama.MENU_CONECTOR);
				}else if(_currentState == IDLE){
					diag.cambioMenu(NuevoDiagrama.MENU_PRINCIPAL);
				}
				invalidate();
			}
			if(_currentState == CONNECTING_ITEMS && !_moveFlag){
				_currentState = ITEM_SELECTED;
				_diagrama.getSelectedItem().set_currentState(Componente.SELECTED);
				invalidate();
			}
			_moveFlag = false;
		}

		return true;
	}


	private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

		@Override
		public boolean onScale(ScaleGestureDetector detector) {
			_currentState = SCALING;
			_Scale *= detector.getScaleFactor();
			_Scale = Math.max(MIN_ZOOM, Math.min(_Scale, MAX_ZOOM));
			invalidate();
			return true;
		}

	}

	public static VistaDiagrama getVista(){
		return _instance;
	}

	public static void resetFocusStatico(){
		_instance.getDiagrama().resetFocus();
		_instance.invalidate();
	}

	public void Conexion() {
		_currentState = CONNECTING_ITEMS;
		_diagrama.getSelectedItem().set_currentState(Componente.CONNECTING);
		invalidate();
	}

	public void nuevaClase()
	{
		_currentState= CREATING_ITEM;
		_tipoComponente = "Clase";
		showHelpNewElement = true;
		invalidate();
	}

	public void nuevaInterfaz() {
		_currentState= CREATING_ITEM;
		_tipoComponente = "Interface";
		showHelpNewElement = true;
		invalidate();		
	}

	public void nuevaClaseAbstract() {
		_currentState= CREATING_ITEM;
		_tipoComponente = "Abstract";
		showHelpNewElement = true;
		invalidate();		
	}
	
	public void agregarAtributo() {
		AtributoComponente myDialog = new AtributoComponente(this.getContext());		
		myDialog.show();
		invalidate();
	}

	public void modificarAtributo() {
		AtributoModif myDialog = new AtributoModif(getContext());
		myDialog.show();
		invalidate();
	}

	public void Guardar(String FileName){

	}
	
	public void ExportarPNG(String FileName,int sideMargins){
		_diagrama.resetFocus();
		Canvas canvas = null;
		Bitmap bmpBase = null;
		FileOutputStream fos = null;

		bmpBase = Bitmap.createBitmap(_diagrama.getDiagramWidth()+(sideMargins*2),_diagrama.getDiagramHeight()+(sideMargins*2) , Bitmap.Config.ARGB_8888);
		canvas = new Canvas(bmpBase);
		super.onDraw(canvas);
		canvas.drawPaint(_backgroundPaint);
		_diagrama.Dibujar(canvas,_diagrama.getDiagramXoffSet()+sideMargins , _diagrama.getDiagramYoffSet()+sideMargins, 1);
		try
		{
			fos = new FileOutputStream(Environment.getExternalStorageDirectory()+"/"+FileName+".png");
			bmpBase.compress(Bitmap.CompressFormat.PNG, 100, fos);
			Toast.makeText(getContext(), "Listo", Toast.LENGTH_LONG).show();
			fos.flush();
			fos.close();
			fos = null;
		}
		catch (IOException e)
		{
			System.out.print(e.getMessage());
			Toast.makeText(getContext(), "Se jodio esa vaina", Toast.LENGTH_LONG).show();
		}
		finally
		{
			if (fos != null)
			{
				try
				{
					fos.close();
					fos = null;
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}
	}

	public void agregarMetodo() {
		NuevoMetodoComponente myDialog = new NuevoMetodoComponente(this.getContext(),_tipoComponente);		
		myDialog.show();
		invalidate();		
	}

	public void modificarMetodo(ArrayAdapter<String> adapter) {
		SeleccionarMetodoComponente myDialog = new SeleccionarMetodoComponente(this.getContext(), adapter,_tipoComponente);		
		myDialog.show();
		invalidate();
	}

	public void editarRelacion() {
		EditarConector myDialog = new EditarConector(this.getContext());		
		myDialog.show();
		invalidate();
	}

}


